package com.knife.common.utils;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.knife.common.constants.BaseConstants;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author tianhao.luo@hand-china.com
 * @version 1.0
 * @date 2022年03月10日 星期四 1:19 下午
 * @description
 * @since 1.0
 */
public class KnifeStringUtil {
    /**
     * 将"${realName}(${realName})的单据待关闭"这类模版进行解析 替换其中的${}为obj中的属性值
     *
     * @param obj      数据提供对象
     * @param template 模版
     * @return 解析模版
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/1/8 1:27 下午
     * @since 1.0
     */
    public static <T> String resolveStr(T obj, String template) {
        char[] chars = template.toCharArray();
        boolean start = false;
        int startIndex = -1, endIndex = -1;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '$') {
                start = true;
                startIndex = i + 2;
            } else if (start && chars[i] == '}') {
                start = false;
                endIndex = i;
            } else if (!start) {
                sb.append(chars[i]);
            }
            if (startIndex != -1 && endIndex != -1) {
                char[] paramChars = Arrays.copyOfRange(chars, startIndex, endIndex);
                String param = new String(paramChars);
                try {
                    Object field = FieldUtils.readDeclaredField(obj, param, true);
                    if (Objects.nonNull(field)) {
                        if (field instanceof Date) {
                            // 支持格式化
                            Field declaredField = FieldUtils.getDeclaredField(obj.getClass(), param, true);
                            JsonFormat annotation = declaredField.getAnnotation(JsonFormat.class);
                            SimpleDateFormat sdf;
                            if (annotation != null && !StringUtils.isEmpty(annotation.pattern())) {
                                sdf = new SimpleDateFormat(annotation.pattern());
                            } else {
                                sdf = new SimpleDateFormat(BaseConstants.Pattern.DATETIME);
                            }
                            sb.append(sdf.format(field));
                        } else if (field instanceof BigDecimal) {
                            // 支持格式化
                            Field declaredField = FieldUtils.getDeclaredField(obj.getClass(), param, true);
                            JsonFormat annotation = declaredField.getAnnotation(JsonFormat.class);
                            DecimalFormat decimalFormat;
                            if (annotation != null && !StringUtils.isEmpty(annotation.pattern())) {
                                decimalFormat = new DecimalFormat(annotation.pattern());
                                sb.append(decimalFormat.format(field));
                            } else {
                                sb.append(((BigDecimal) field).toPlainString());
                            }
                        } else {
                            sb.append(field.toString());
                        }
                    } else {
                        sb.append("null");
                    }
                } catch (Exception e) {
                    sb.append("|errorResolve(").append(param).append(")|");
                }
                startIndex = -1;
                endIndex = -1;
            }
        }
        return sb.toString();
    }


    /**
     * 将"${realName}(${realName})的单据待关闭"这类模版进行解析 替换其中的${}为obj中的属性值
     *
     * @param map      数据提供对象
     * @param template 模版
     * @return 解析模版
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/1/8 1:27 下午
     * @since 1.0
     */
    public static String resolveStr(Map<String, String> map, String template) {
        char[] chars = template.toCharArray();
        boolean start = false;
        int startIndex = -1, endIndex = -1;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '$') {
                start = true;
                startIndex = i + 2;
            } else if (start && chars[i] == '}') {
                start = false;
                endIndex = i;
            } else if (!start) {
                sb.append(chars[i]);
            }
            if (startIndex != -1 && endIndex != -1) {
                char[] paramChars = Arrays.copyOfRange(chars, startIndex, endIndex);
                String param = new String(paramChars);
                String field = map.get(param);
                if (!StringUtils.isEmpty(field)) {
                    sb.append(field);
                } else {
                    sb.append("null");
                }
                startIndex = -1;
                endIndex = -1;
            }
        }
        return sb.toString();
    }


    /**
     * @param obj      参数对象
     * @param template 消息模板
     * @return 将消息模版中的参数解析出来转化为map
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/1/8 4:22 下午
     * @since 1.0
     */
    public static <T> Map<String, String> resolveToInnerMsgParam(T obj, String template) {
        Set<String> paramSet = resolveStrParam(template);
        HashMap<String, String> map = new HashMap<>(paramSet.size());
        paramSet.forEach(param -> {
            String value = "null";
            try {
                Object field = FieldUtils.readDeclaredField(obj, param, true);
                if (Objects.nonNull(field)) {
                    if (field instanceof Date) {
                        // 支持格式化
                        Field declaredField = FieldUtils.getDeclaredField(obj.getClass(), param, true);
                        JsonFormat annotation = declaredField.getAnnotation(JsonFormat.class);
                        SimpleDateFormat sdf;
                        if (annotation != null && !StringUtils.isEmpty(annotation.pattern())) {
                            sdf = new SimpleDateFormat(annotation.pattern());
                        } else {
                            sdf = new SimpleDateFormat(BaseConstants.Pattern.DATETIME);
                        }
                        value = sdf.format(field);
                    } else if (field instanceof BigDecimal) {
                        // 支持格式化
                        Field declaredField = FieldUtils.getDeclaredField(obj.getClass(), param, true);
                        JsonFormat annotation = declaredField.getAnnotation(JsonFormat.class);
                        DecimalFormat decimalFormat;
                        if (annotation != null && !StringUtils.isEmpty(annotation.pattern())) {
                            decimalFormat = new DecimalFormat(annotation.pattern());
                            value = decimalFormat.format(field);
                        } else {
                            value = ((BigDecimal) field).toPlainString();
                        }
                    } else {
                        value = field.toString();
                    }
                }
            } catch (IllegalAccessException e) {
                value = "|errorResolve(" + param + ")|";
            }
            map.put(param, value);
        });
        return map;
    }

    /**
     * @param template 模版
     * @return 模版中的参数
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/1/8 4:10 下午
     * @since 1.0
     */
    public static Set<String> resolveStrParam(String template) {
        Set<String> set = new HashSet<>();
        char[] chars = template.toCharArray();
        boolean start = false;
        int startIndex = -1, endIndex = -1;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '$') {
                start = true;
                startIndex = i + 2;
            } else if (start && chars[i] == '}') {
                start = false;
                endIndex = i;
            }
            if (startIndex != -1 && endIndex != -1) {
                char[] paramChars = Arrays.copyOfRange(chars, startIndex, endIndex);
                String param = new String(paramChars);
                set.add(param);
                startIndex = -1;
                endIndex = -1;
            }
        }
        return set;
    }


    /**
     * 将驼峰风格替换为下划线风格，注意默认转化为全大写
     *
     * @param str 驼峰
     * @return 下划线风格
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/4/9 6:21 下午
     * @since 1.0
     */
    public static String camelhumpToUnderline(String str) {
        if (!StringUtils.hasText(str)) {
            return str;
        }
        final int size;
        final char[] chars;
        final StringBuilder sb = new StringBuilder(
                (size = (chars = str.toCharArray()).length) * 3 / 2 + 1);
        char c;
        for (int i = 0; i < size; i++) {
            c = chars[i];
            if (isUppercaseAlpha(c)) {
                sb.append('_').append(c);
            } else {
                sb.append(toUpperAscii(c));
            }
        }
        return sb.charAt(0) == '_' ? sb.substring(1) : sb.toString();
    }


    /**
     * 将驼峰风格替换为中划线风格
     *
     * @param str 驼峰
     * @param upFlag 是否转化为大写
     * @return 下划线风格
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/4/9 6:21 下午
     * @since 1.0
     */
    public static String camelhumpToMiddleline(String str, boolean upFlag) {
        if (!StringUtils.hasText(str)) {
            return str;
        }
        final int size;
        final char[] chars;
        final StringBuilder sb = new StringBuilder(
                (size = (chars = str.toCharArray()).length) * 3 / 2 + 1);
        char c;
        for (int i = 0; i < size; i++) {
            c = chars[i];
            if (i > 0 && isUppercaseAlpha(c)) {
                sb.append(BaseConstants.Symbol.MIDDLE_LINE).append(upFlag ? toUpperAscii(c) : toLowerAscii(c));
            } else {
                sb.append(upFlag ? toUpperAscii(c) : toLowerAscii(c));
            }
        }
        return sb.toString();
    }


    /**
     * 将下划线风格替换为驼峰风格
     *
     * @param str 下划线风格
     * @return 驼峰
     * @description
     * @version 1.0
     * @author tianhao.luo@hand-china.com
     * @date 2022/4/9 6:21 下午
     * @since 1.0
     */
    public static String underlineToCamelhump(String str) {
        Matcher matcher = Pattern.compile("_[a-z]").matcher(str);
        StringBuilder builder = new StringBuilder(str);
        for (int i = 0; matcher.find(); i++) {
            builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase());
        }
        if (Character.isUpperCase(builder.charAt(0))) {
            builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0))));
        }
        return builder.toString();
    }

    public static boolean isUppercaseAlpha(char c) {
        return (c >= 'A') && (c <= 'Z');
    }

    public static boolean isLowercaseAlpha(char c) {
        return (c >= 'a') && (c <= 'z');
    }

    public static char toUpperAscii(char c) {
        if (isLowercaseAlpha(c)) {
            c -= (char) 0x20;
        }
        return c;
    }

    public static char toLowerAscii(char c) {
        if (isUppercaseAlpha(c)) {
            c += (char) 0x20;
        }
        return c;
    }
}
